home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 23 / CU Amiga - Super CD-ROM 23 (June 1998).iso / CUCD / Games / ADoomPPC / src / amiga_sound.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-01  |  23.6 KB  |  871 lines

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdarg.h>
  4. #include <string.h>
  5.  
  6. #include <exec/exec.h>
  7. #include <dos/dos.h>
  8. #include <graphics/gfxbase.h>
  9. #include <devices/audio.h>
  10.  
  11. #include <proto/exec.h>
  12. #include <proto/dos.h>
  13. #include <proto/graphics.h>
  14.  
  15. /* #include <math.h> */
  16.  
  17. #include "z_zone.h"
  18.  
  19. #include "i_system.h"
  20. #include "i_sound.h"
  21. #include "m_argv.h"
  22. #include "m_misc.h"
  23. #include "w_wad.h"
  24.  
  25. #include "doomdef.h"
  26.  
  27.  
  28. // Any value of numChannels set
  29. // by the defaults code in M_misc is now clobbered by I_InitSound().
  30. // number of channels available for sound effects
  31.  
  32. extern int numChannels;
  33.  
  34. extern struct ExecBase *SysBase;
  35.  
  36. #define    BeginIO(ioRequest)    _BeginIO(ioRequest)
  37.  
  38. __inline void
  39. _BeginIO(struct IORequest *ioRequest)
  40. {
  41. struct Caos    MyCaos;
  42.     MyCaos.M68kCacheMode    =    IF_CACHEFLUSHALL;
  43. //    MyCaos.M68kStart    =    NULL;
  44. //    MyCaos.M68kSize        =    0;
  45.     MyCaos.PPCCacheMode    =    IF_CACHEFLUSHALL;
  46. //    MyCaos.PPCStart        =    NULL;
  47. //    MyCaos.PPCSize        =    0;
  48.     MyCaos.a1        =(ULONG) ioRequest;
  49.     MyCaos.caos_Un.Offset    =    (-30);
  50.     MyCaos.a6        =(ULONG) ioRequest->io_Device;
  51.     PPCCallOS(&MyCaos);
  52. }
  53.  
  54. /**********************************************************************/
  55. #define MAXSFXVOICES    16   /* max number of Sound Effects with server */
  56. #define MAXNUMCHANNELS   4   /* max number of Amiga sound channels */
  57. #define CHIP_CACHE_SIZE 12   /* number of waveforms allowed in chipmem */
  58.  
  59. struct chip_cache_info {
  60.   int id;
  61.   ULONG age;
  62.   char *chip_data;
  63.   int len;
  64. };
  65.  
  66. struct channel_info {
  67.   struct MsgPort *audio_mp;
  68.   struct IOAudio *audio_io;
  69.   BOOL sound_in_progress;
  70. };
  71.  
  72. /**********************************************************************/
  73. // The actual lengths of all sound effects.
  74. static int lengths[NUMSFX];
  75.  
  76. static struct MsgPort *audio_mp = NULL;
  77. static struct IOAudio *audio_io = NULL;
  78. static BOOL audio_is_open = FALSE;
  79.  
  80. static struct channel_info channel_info[MAXNUMCHANNELS] = {
  81.   {NULL, NULL, FALSE},
  82.   {NULL, NULL, FALSE},
  83.   {NULL, NULL, FALSE},
  84.   {NULL, NULL, FALSE},
  85. };
  86.  
  87. /* cache up to CHIP_CACHE_SIZE sound effects in chipmem, rest in fastmem */
  88. static struct chip_cache_info chip_cache_info[CHIP_CACHE_SIZE] = {
  89.   {-1, 0, NULL, -1},
  90.   {-1, 0, NULL, -1},
  91.   {-1, 0, NULL, -1},
  92.   {-1, 0, NULL, -1},
  93.   {-1, 0, NULL, -1},
  94.   {-1, 0, NULL, -1},
  95.   {-1, 0, NULL, -1},
  96.   {-1, 0, NULL, -1},
  97.   {-1, 0, NULL, -1},
  98.   {-1, 0, NULL, -1},
  99.   {-1, 0, NULL, -1},
  100.   {-1, 0, NULL, -1}
  101. };
  102.  
  103. static ULONG age = 1;
  104. static UWORD period_table[256];
  105.  
  106. static int changepitch;
  107. /* sampling freq (Hz) for each pitch step when changepitch is TRUE
  108.    calculated from (2^((i-128)/64))*11025
  109.    I'm not sure if this is the right formula */
  110. static UWORD freqs[256] = {
  111.   2756, 2786, 2817, 2847, 2878, 2910, 2941, 2973,
  112.   3006, 3038, 3072, 3105, 3139, 3173, 3208, 3242,
  113.   3278, 3313, 3350, 3386, 3423, 3460, 3498, 3536,
  114.   3574, 3613, 3653, 3692, 3733, 3773, 3814, 3856,
  115.   3898, 3940, 3983, 4027, 4071, 4115, 4160, 4205,
  116.   4251, 4297, 4344, 4391, 4439, 4487, 4536, 4586,
  117.   4635, 4686, 4737, 4789, 4841, 4893, 4947, 5001,
  118.   5055, 5110, 5166, 5222, 5279, 5336, 5394, 5453,
  119.   5513, 5573, 5633, 5695, 5757, 5819, 5883, 5947,
  120.   6011, 6077, 6143, 6210, 6278, 6346, 6415, 6485,
  121.   6556, 6627, 6699, 6772, 6846, 6920, 6996, 7072,
  122.   7149, 7227, 7305, 7385, 7465, 7547, 7629, 7712,
  123.   7796, 7881, 7967, 8053, 8141, 8230, 8319, 8410,
  124.   8501, 8594, 8688, 8782, 8878, 8975, 9072, 9171,
  125.   9271, 9372, 9474, 9577, 9681, 9787, 9893, 10001,
  126.   10110, 10220, 10331, 10444, 10558, 10673, 10789, 10906,
  127.   11025, 11145, 11266, 11389, 11513, 11638, 11765, 11893,
  128.   12023, 12154, 12286, 12420, 12555, 12692, 12830, 12970,
  129.   13111, 13254, 13398, 13544, 13691, 13841, 13991, 14144,
  130.   14298, 14453, 14611, 14770, 14931, 15093, 15258, 15424,
  131.   15592, 15761, 15933, 16107, 16282, 16459, 16639, 16820,
  132.   17003, 17188, 17375, 17564, 17756, 17949, 18144, 18342,
  133.   18542, 18744, 18948, 19154, 19363, 19574, 19787, 20002,
  134.   20220, 20440, 20663, 20888, 21115, 21345, 21578, 21812,
  135.   22050, 22290, 22533, 22778, 23026, 23277, 23530, 23787,
  136.   24046, 24308, 24572, 24840, 25110, 25384, 25660, 25940,
  137.   26222, 26508, 26796, 27088, 27383, 27681, 27983, 28287,
  138.   28595, 28907, 29221, 29540, 29861, 30187, 30515, 30848,
  139.   31183, 31523, 31866, 32213, 32564, 32919, 33277, 33639,
  140.   34006, 34376, 34750, 35129, 35511, 35898, 36289, 36684,
  141.   37084, 37487, 37896, 38308, 38725, 39147, 39573, 40004,
  142.   40440, 40880, 41325, 41775, 42230, 42690, 43155, 43625
  143. };
  144.  
  145. /**********************************************************************/
  146.  
  147. static struct Library *DoomSndBase = NULL;
  148.  
  149. static __inline void Sfx_SetVol(int vol)
  150. {
  151. struct Caos    MyCaos;
  152.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  153. //    MyCaos.M68kStart        =    NULL;
  154. //    MyCaos.M68kSize            =    0;
  155.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  156. //    MyCaos.PPCStart            =    NULL;
  157. //    MyCaos.PPCSize            =    0;
  158.     MyCaos.d0            =    vol;
  159.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-30);
  160.     PPCCallM68k(&MyCaos);
  161. }
  162.  
  163. static __inline void Sfx_Start(char *wave, int cnum, int step, int vol, int sep, int length)
  164. {
  165. struct Caos    MyCaos;
  166.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHALL;
  167. //    MyCaos.M68kStart        =    NULL;
  168. //    MyCaos.M68kSize            =    0;
  169.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHALL;
  170. //    MyCaos.PPCStart            =    NULL;
  171. //    MyCaos.PPCSize            =    0;
  172.     MyCaos.a0            = (ULONG) wave;
  173.     MyCaos.d0            =    cnum;
  174.     MyCaos.d1            =    step;
  175.     MyCaos.d2            =    vol;
  176.     MyCaos.d3            =    sep;
  177.     MyCaos.d4            =    length;
  178.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-36);
  179.     PPCCallM68k(&MyCaos);
  180. }
  181.  
  182. static __inline void Sfx_Update(int cnum, int step, int vol, int sep)
  183. {
  184. struct Caos    MyCaos;
  185.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  186. //    MyCaos.M68kStart        =    NULL;
  187. //    MyCaos.M68kSize            =    0;
  188.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  189. //    MyCaos.PPCStart            =    NULL;
  190. //    MyCaos.PPCSize            =    0;
  191.     MyCaos.d0            =    cnum;
  192.     MyCaos.d1            =    step;
  193.     MyCaos.d2            =    vol;
  194.     MyCaos.d3            =    sep;
  195.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-42);
  196.     PPCCallM68k(&MyCaos);
  197. }
  198.  
  199. static __inline void Sfx_Stop(int cnum)
  200. {
  201. struct Caos    MyCaos;
  202.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  203. //    MyCaos.M68kStart        =    NULL;
  204. //    MyCaos.M68kSize            =    0;
  205.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  206. //    MyCaos.PPCStart            =    NULL;
  207. //    MyCaos.PPCSize            =    0;
  208.     MyCaos.d0            =    cnum;
  209.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-48);
  210.     PPCCallM68k(&MyCaos);
  211. }
  212.  
  213. static __inline int Sfx_Done(int cnum)
  214. {
  215. struct Caos    MyCaos;
  216.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  217. //    MyCaos.M68kStart        =    NULL;
  218. //    MyCaos.M68kSize            =    0;
  219.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  220. //    MyCaos.PPCStart            =    NULL;
  221. //    MyCaos.PPCSize            =    0;
  222.     MyCaos.d0            =    cnum;
  223.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-54);
  224.     return((int)PPCCallM68k(&MyCaos));
  225. }
  226.  
  227. static __inline void Mus_SetVol(int vol)
  228. {
  229. struct Caos    MyCaos;
  230.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  231. //    MyCaos.M68kStart        =    NULL;
  232. //    MyCaos.M68kSize            =    0;
  233.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  234. //    MyCaos.PPCStart            =    NULL;
  235. //    MyCaos.PPCSize            =    0;
  236.     MyCaos.d0            =    vol;
  237.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-60);
  238.     PPCCallM68k(&MyCaos);
  239. }
  240.  
  241. static __inline int Mus_Register(void *musdata)
  242. {
  243. struct Caos    MyCaos;
  244.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHALL;
  245. //    MyCaos.M68kStart        =    NULL;
  246. //    MyCaos.M68kSize            =    0;
  247.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHALL;
  248. //    MyCaos.PPCStart            =    NULL;
  249. //    MyCaos.PPCSize            =    0;
  250.     MyCaos.a0            = (ULONG) musdata;
  251.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-66);
  252.     return((int)PPCCallM68k(&MyCaos));
  253. }
  254.  
  255. static __inline void Mus_Unregister(int handle)
  256. {
  257. struct Caos    MyCaos;
  258.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  259. //    MyCaos.M68kStart        =    NULL;
  260. //    MyCaos.M68kSize            =    0;
  261.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  262. //    MyCaos.PPCStart            =    NULL;
  263. //    MyCaos.PPCSize            =    0;
  264.     MyCaos.d0            =    handle;
  265.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-72);
  266.     PPCCallM68k(&MyCaos);
  267. }
  268.  
  269. static __inline void Mus_Play(int handle, int looping)
  270. {
  271. struct Caos    MyCaos;
  272.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  273. //    MyCaos.M68kStart        =    NULL;
  274. //    MyCaos.M68kSize            =    0;
  275.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  276. //    MyCaos.PPCStart            =    NULL;
  277. //    MyCaos.PPCSize            =    0;
  278.     MyCaos.d0            =    handle;
  279.     MyCaos.d1            =    looping;
  280.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-78);
  281.     PPCCallM68k(&MyCaos);
  282. }
  283.  
  284. static __inline void Mus_Stop(int handle)
  285. {
  286. struct Caos    MyCaos;
  287.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  288. //    MyCaos.M68kStart        =    NULL;
  289. //    MyCaos.M68kSize            =    0;
  290.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  291. //    MyCaos.PPCStart            =    NULL;
  292. //    MyCaos.PPCSize            =    0;
  293.     MyCaos.d0            =    handle;
  294.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-84);
  295.     PPCCallM68k(&MyCaos);
  296. }
  297.  
  298. static __inline void Mus_Pause(int handle)
  299. {
  300. struct Caos    MyCaos;
  301.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  302. //    MyCaos.M68kStart        =    NULL;
  303. //    MyCaos.M68kSize            =    0;
  304.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  305. //    MyCaos.PPCStart            =    NULL;
  306. //    MyCaos.PPCSize            =    0;
  307.     MyCaos.d0            =    handle;
  308.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-90);
  309.     PPCCallM68k(&MyCaos);
  310. }
  311.  
  312. static __inline void Mus_Resume(int handle)
  313. {
  314. struct Caos    MyCaos;
  315.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  316. //    MyCaos.M68kStart        =    NULL;
  317. //    MyCaos.M68kSize            =    0;
  318.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  319. //    MyCaos.PPCStart            =    NULL;
  320. //    MyCaos.PPCSize            =    0;
  321.     MyCaos.d0            =    handle;
  322.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-96);
  323.     PPCCallM68k(&MyCaos);
  324. }
  325.  
  326. static __inline int MUS_Done(int handle)
  327. {
  328. struct Caos    MyCaos;
  329.     MyCaos.M68kCacheMode        =    IF_CACHEFLUSHNO;
  330. //    MyCaos.M68kStart        =    NULL;
  331. //    MyCaos.M68kSize            =    0;
  332.     MyCaos.PPCCacheMode        =    IF_CACHEFLUSHNO;
  333. //    MyCaos.PPCStart            =    NULL;
  334. //    MyCaos.PPCSize            =    0;
  335.     MyCaos.d0            =    handle;
  336.     MyCaos.caos_Un.Offset        =       (((int)DoomSndBase)-102);
  337.     return((int)PPCCallM68k(&MyCaos));
  338. }
  339.  
  340.  
  341. /**********************************************************************/
  342. //
  343. // This function loads the sound data for sfxname from the WAD lump,
  344. // and returns a ptr to the data in fastmem and its length in len.
  345. //
  346. static void *getsfx (char *sfxname, int *len)
  347. {
  348.   unsigned char*      sfx;
  349.   unsigned char*      paddedsfx;
  350.   int                 i;
  351.   int                 size;
  352.   int                 paddedsize;
  353.   char                name[20];
  354.   int                 sfxlump;
  355.  
  356.   // Get the sound data from the WAD, allocate lump
  357.   //  in zone memory.
  358.   sprintf(name, "ds%s", sfxname);
  359.  
  360.   // Now, there is a severe problem with the
  361.   //  sound handling, in it is not (yet/anymore)
  362.   //  gamemode aware. That means, sounds from
  363.   //  DOOM II will be requested even with DOOM
  364.   //  shareware.
  365.   // The sound list is wired into sounds.c,
  366.   //  which sets the external variable.
  367.   // I do not do runtime patches to that
  368.   //  variable. Instead, we will use a
  369.   //  default sound for replacement.
  370.   if (W_CheckNumForName(name) == -1)
  371.     sfxlump = W_GetNumForName("dspistol");
  372.   else
  373.     sfxlump = W_GetNumForName (name);
  374.  
  375.   size = W_LumpLength (sfxlump);
  376.  
  377.   // Debug.
  378.   // fprintf( stderr, "." );
  379.   // fprintf( stderr, " -loading  %s (lump %d, %d bytes)\n",
  380.   //         sfxname, sfxlump, size );
  381.   //fflush( stderr );
  382.  
  383.   sfx = (unsigned char*)W_CacheLumpNum (sfxlump, PU_STATIC);
  384.  
  385.   // Allocate from zone memory.
  386.   paddedsfx = (unsigned char*)Z_Malloc (size, PU_STATIC, 0);
  387.   // ddt: (unsigned char *) realloc(sfx, paddedsize+8);
  388.   // This should interfere with zone memory handling,
  389.   //  which does not kick in in the soundserver.
  390.  
  391.   // Now copy and pad.
  392.   for (i = 0; i < size; i++)
  393.     paddedsfx[i] = sfx[i] ^ 0x80;
  394.   /* memcpy (paddedsfx, sfx, size); */
  395.  
  396.   // Remove the cached lump.
  397.   Z_Free( sfx );
  398.  
  399.   // Preserve padded length.
  400.   *len = size;
  401.  
  402.   // Return allocated padded data.
  403.   return (void *) (paddedsfx /* + 8 */);
  404. }
  405.  
  406. /**********************************************************************/
  407. // Init at program start...
  408. void I_InitSound (void)
  409. {
  410.   int i;
  411.   struct channel_info *c;
  412.   UBYTE chans[1];
  413.   ULONG clock_constant;   /* see Amiga Hardware Manual page 141 */
  414.  
  415.   if (M_CheckParm("-nosfx"))
  416.     return;
  417.  
  418.   // Secure and configure sound device first.
  419.   fprintf( stderr, "I_InitSound: ");
  420.  
  421.   if ((DoomSndBase = OpenLibrary ("doomsound.library",37)) != NULL) {
  422.     Sfx_SetVol(64);
  423.     Mus_SetVol(64);
  424.     numChannels = 16;
  425.   } else {
  426.     fprintf (stderr, " Cannot open doomsound.library, music not available.\n" );
  427.     fprintf( stderr, "I_InitSound: ");
  428.   }
  429.  
  430.   if (DoomSndBase == NULL) {
  431.     numChannels = 4;
  432.  
  433.     if ((audio_mp = CreatePort (NULL, 0)) == NULL ||
  434.         (audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
  435.                                              MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  436.       I_Error ("CreatePort() or AllocMem() failed");
  437.  
  438.     chans[0] = (1 << numChannels) - 1; /* numchannels Amiga audio channels */
  439.     audio_io->ioa_Request.io_Message.mn_ReplyPort = audio_mp;
  440.     audio_io->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
  441.     audio_io->ioa_AllocKey = 0;
  442.     audio_io->ioa_Data = chans;
  443.     audio_io->ioa_Length = sizeof(chans);
  444.  
  445.     if (OpenDevice (AUDIONAME, 0, (struct IORequest *)audio_io, 0) != 0)
  446.       I_Error ("OpenDevice(\"audio.device\") failed");
  447.     audio_is_open = TRUE;
  448.  
  449.     for (i = 0; i < numChannels; i++) {
  450.       c = &channel_info[i];
  451.       if ((c->audio_mp = CreatePort (NULL, 0)) == NULL ||
  452.           (c->audio_io = (struct IOAudio *)AllocMem(sizeof(struct IOAudio),
  453.                                              MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  454.         I_Error ("CreatePort() or AllocMem() failed");
  455.       *c->audio_io = *audio_io;
  456.       c->audio_io->ioa_Request.io_Message.mn_ReplyPort = c->audio_mp;
  457.       c->audio_io->ioa_Request.io_Unit = (struct Unit *)(1 << i);
  458.     }
  459.   }
  460.  
  461.   if ((GfxBase->DisplayFlags & REALLY_PAL) == 0)
  462.     clock_constant = 3579545;   /* NTSC */
  463.   else
  464.     clock_constant = 3546895;   /* PAL */
  465.   changepitch = M_CheckParm ("-changepitch");
  466.   for (i = 0; i < 256; i++) {
  467.     if (changepitch)
  468.       period_table[i] = ((clock_constant << 1) + freqs[i]) /
  469.                         (((ULONG)freqs[i]) << 1);
  470.     else
  471.       period_table[i] = ((clock_constant << 1) + 11025) / ((11025) << 1);
  472.   }
  473.  
  474.   fprintf (stderr, " configured audio device\n" );
  475.  
  476.  
  477.   // Initialize external data (all sounds) at start, keep static.
  478.   fprintf (stderr, "I_InitSound: ");
  479.  
  480.   for (i = 1; i < NUMSFX; i++) {
  481.     // Alias? Example is the chaingun sound linked to pistol.
  482.     if (!S_sfx[i].link) {
  483.       // Load data from WAD file.
  484.       S_sfx[i].data = getsfx (S_sfx[i].name, &lengths[i]);
  485.     } else {
  486.       // Previously loaded already?
  487.       S_sfx[i].data = S_sfx[i].link->data;
  488.       lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)];
  489.     }
  490.   }
  491.  
  492.   fprintf (stderr, " pre-cached all sound data\n");
  493.  
  494.   // Finished initialization.
  495.   fprintf (stderr, "I_InitSound: sound module ready\n");
  496. }
  497.  
  498. /**********************************************************************/
  499. // ... update sound buffer and audio device at runtime...
  500. void I_UpdateSound (void)
  501. {
  502.   /* fprintf (stderr, "I_UpdateSound()\n"); */
  503. }
  504.  
  505. /**********************************************************************/
  506. // ... update sound buffer and audio device at runtime...
  507. void I_SubmitSound (void)
  508. {
  509.   /* fprintf (stderr, "I_SubmitSound()\n"); */
  510.   // Write it to DSP device.
  511.   // write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL);
  512. }
  513.  
  514. /**********************************************************************/
  515. // ... shut down and relase at program termination.
  516. void I_ShutdownSound (void)
  517. {
  518.   int i;
  519.  
  520.   fprintf (stderr, "I_ShutdownSound()\n");
  521.  
  522.   if (DoomSndBase != NULL) {
  523.     CloseLibrary (DoomSndBase);
  524.     DoomSndBase = NULL;
  525.   }
  526.  
  527.   if (audio_is_open) {
  528.     for (i = 0; i < numChannels; i++)
  529.       I_StopSound (i);
  530.     audio_io->ioa_Request.io_Unit = (struct Unit *)
  531.                      ((1 << numChannels) - 1);  /* free numChannels channels */
  532.     CloseDevice ((struct IORequest *)audio_io);
  533.     audio_is_open = FALSE;
  534.   }
  535.   for (i = 0; i < CHIP_CACHE_SIZE; i++) {
  536.     if (chip_cache_info[i].chip_data != NULL) {
  537.       FreeMem (chip_cache_info[i].chip_data, chip_cache_info[i].len);
  538.       chip_cache_info[i].chip_data = NULL;
  539.     }
  540.   }
  541.   for (i = 0; i < MAXNUMCHANNELS; i++) {
  542.     if (channel_info[i].audio_io != NULL) {
  543.       FreeMem (channel_info[i].audio_io, sizeof(struct IOAudio));
  544.       channel_info[i].audio_io = NULL;
  545.     }
  546.     if (channel_info[i].audio_mp != NULL) {
  547.       DeletePort (channel_info[i].audio_mp);
  548.       channel_info[i].audio_mp = NULL;
  549.     }
  550.   }
  551.   if (audio_io != NULL) {
  552.     FreeMem (audio_io, sizeof(struct IOAudio));
  553.     audio_io = NULL;
  554.   }
  555.   if (audio_mp != NULL) {
  556.     DeletePort (audio_mp);
  557.     audio_mp = NULL;
  558.   }
  559. }
  560.  
  561. /**********************************************************************/
  562. /**********************************************************************/
  563. //
  564. //  SFX I/O
  565. //
  566.  
  567. /**********************************************************************/
  568. // Initialize number of channels
  569. void I_SetChannels (void)
  570. {
  571. }
  572.  
  573. /**********************************************************************/
  574. // Get raw data lump index for sound descriptor.
  575. int I_GetSfxLumpNum (sfxinfo_t *sfx)
  576. {
  577.   char namebuf[9];
  578.  
  579.   /* fprintf (stderr, "I_GetSfxLumpNum()\n"); */
  580.   sprintf(namebuf, "ds%s", sfx->name);
  581.   return W_GetNumForName(namebuf);
  582. }
  583.  
  584. /**********************************************************************/
  585. // Find chip cache entry used longest ago and re-use it.
  586. static int cache_chip_data (int id)
  587. {
  588.   int i, mini;
  589.   ULONG minage;
  590.   struct chip_cache_info *c;
  591.  
  592.   if (age == 0xfffffffe)
  593.     I_Error ("Age overflow in cache_chip_data()");
  594.   minage = 0xffffffff;
  595.   mini = 0;
  596.   for (i = 0; i < CHIP_CACHE_SIZE; i++) {
  597.     c = &chip_cache_info[i];
  598.     if (c->id == id) {
  599.       c->age = age++;
  600.       return i;
  601.     }
  602.     if (c->age < minage) {
  603.       minage = c->age;
  604.       mini = i;
  605.     }
  606.   }
  607.   c = &chip_cache_info[mini];
  608.   if (c->chip_data != NULL) {
  609.     FreeMem (c->chip_data, c->len);
  610.     c->chip_data = NULL;
  611.   }
  612.   c->id = id;
  613.   c->age = age++;
  614.   if ((c->chip_data = AllocMem (lengths[id], MEMF_CHIP)) == NULL)
  615.     I_Error ("Out of CHIP memory allocating %d bytes", lengths[id]);
  616. //  memcpy (c->chip_data, S_sfx[id].data, lengths[id]);
  617.   CopyMem (S_sfx[id].data, c->chip_data, lengths[id]);
  618.   c->len = lengths[id];
  619.   return mini;
  620. }
  621.  
  622. /**********************************************************************/
  623. // Starts a sound in a particular sound channel.
  624. int I_StartSound (
  625.   int id,
  626.   int cnum,
  627.   int vol,
  628.   int sep,
  629.   int pitch,
  630.   int priority )
  631. {
  632.   struct channel_info *c;
  633.  
  634. /*  fprintf (stderr, "I_StartSound(%d,%d,%d,%d,%d,%d)\n", id, cnum, vol, sep,
  635.               pitch, priority); */
  636.  
  637.   if (DoomSndBase != NULL) {
  638.     I_StopSound(cnum);
  639.     Sfx_Start (S_sfx[id].data, cnum, changepitch ? freqs[pitch] : 11025,
  640.                vol<<3, sep, lengths[id]);
  641.     return cnum;
  642.   }
  643.  
  644.   if (!audio_is_open)
  645.     return 1;
  646.   I_StopSound (cnum);
  647.   c = &channel_info[cnum];
  648.   c->audio_io->ioa_Request.io_Command = CMD_WRITE;
  649.   c->audio_io->ioa_Request.io_Flags = ADIOF_PERVOL;
  650.   c->audio_io->ioa_Data = &chip_cache_info[cache_chip_data (id)].chip_data[8];
  651.   c->audio_io->ioa_Length = lengths[id] - 8;
  652.   c->audio_io->ioa_Period = period_table[pitch];
  653.   c->audio_io->ioa_Volume = vol << 2;
  654.   c->audio_io->ioa_Cycles = 1;
  655.   BeginIO ((struct IORequest *)c->audio_io);
  656.   c->sound_in_progress = TRUE;
  657.   return cnum;
  658. }
  659.  
  660. /**********************************************************************/
  661. // Stops a sound channel.
  662. void I_StopSound(int handle)
  663. {
  664.   /* fprintf (stderr, "I_StopSound(%d)\n", handle); */
  665.  
  666.   if (DoomSndBase != NULL) {
  667.     Sfx_Stop(handle);
  668.     return;
  669.   }
  670.  
  671.   if (!audio_is_open)
  672.     return;
  673.   if (channel_info[handle].sound_in_progress) {
  674.     AbortIO ((struct IORequest *)channel_info[handle].audio_io);
  675.     WaitPort (channel_info[handle].audio_mp);
  676.     GetMsg (channel_info[handle].audio_mp);
  677.     channel_info[handle].sound_in_progress = FALSE;
  678.   }
  679. }
  680.  
  681. /**********************************************************************/
  682. // Called by S_*() functions
  683. //  to see if a channel is still playing.
  684. // Returns 0 if no longer playing, 1 if playing.
  685. int I_SoundIsPlaying(int handle)
  686. {
  687.   /* fprintf (stderr, "I_SoundIsPlaying(%d)\n", handle); */
  688.  
  689.   if (DoomSndBase != NULL) {
  690.     return Sfx_Done(handle) ? 1 : 0;
  691.   }
  692.  
  693.   if (!audio_is_open)
  694.     return 0;
  695.   if (channel_info[handle].sound_in_progress) {
  696.     if (CheckIO ((struct IORequest *)channel_info[handle].audio_io)) {
  697.       WaitPort (channel_info[handle].audio_mp);  /* clears signal & returns immediately */
  698.       GetMsg (channel_info[handle].audio_mp);
  699.       channel_info[handle].sound_in_progress = FALSE;
  700.       return 0;
  701.     } else {
  702.       return 1;
  703.     }
  704.   }
  705.   return 0;
  706. }
  707.  
  708. /**********************************************************************/
  709. // Updates the volume, separation,
  710. //  and pitch of a sound channel.
  711. void
  712. I_UpdateSoundParams
  713. ( int        handle,
  714.   int        vol,
  715.   int        sep,
  716.   int        pitch )
  717. {
  718. /*
  719.   fprintf (stderr, "I_UpdateSoundParams(%d,%d,%d,%d)\n", handle, vol,
  720.            sep, pitch);
  721. */
  722.  
  723.   if (DoomSndBase != NULL) {
  724.     Sfx_Update(handle, changepitch ? freqs[pitch] : 11025, vol<<3, sep);
  725.     return;
  726.   }
  727.  
  728.   if (!audio_is_open)
  729.     return;
  730.   if (channel_info[handle].sound_in_progress) {
  731.     audio_io->ioa_Request.io_Command = ADCMD_PERVOL;
  732.     audio_io->ioa_Request.io_Flags = ADIOF_PERVOL;
  733.     audio_io->ioa_Request.io_Unit = (struct Unit *)(1 << handle);
  734.     audio_io->ioa_Period = period_table[pitch];
  735.     audio_io->ioa_Volume = vol << 2;
  736.     BeginIO ((struct IORequest *)audio_io);
  737.     WaitPort (audio_mp);
  738.     GetMsg (audio_mp);
  739.   }
  740. }
  741.  
  742.  
  743. /**********************************************************************/
  744. /**********************************************************************/
  745. //
  746. // MUSIC API.
  747. //
  748.  
  749. static int looping=0;
  750. static int musicdies=-1;
  751.  
  752. static int music_okay = 0;
  753.  
  754. /**********************************************************************/
  755. //
  756. //  MUSIC I/O
  757. //
  758. void I_InitMusic(void)
  759. {
  760. //  fprintf (stderr, "I_InitMusic()\n");
  761.  
  762.   if (M_CheckParm("-music") && (DoomSndBase != NULL))
  763.     music_okay = 1;
  764. }
  765.  
  766. /**********************************************************************/
  767. void I_ShutdownMusic(void)
  768. {
  769. //  fprintf (stderr, "I_ShutdownMusic()\n");
  770. }
  771.  
  772. /**********************************************************************/
  773. // Volume.
  774. void I_SetMusicVolume(int volume)
  775. {
  776. //  fprintf (stderr, "I_SetMusicVolume(%d)\n", volume);
  777.   snd_MusicVolume = volume;
  778.  
  779.   if (music_okay) {
  780.     Mus_SetVol((volume<<2)+4);
  781.   }
  782. }
  783.  
  784. /**********************************************************************/
  785. // PAUSE game handling.
  786. void I_PauseSong(int handle)
  787. {
  788. //  fprintf (stderr, "I_PauseSong(%d)\n", handle);
  789.  
  790.   if (music_okay) {
  791.     Mus_Pause(handle);
  792.   }
  793. }
  794.  
  795. /**********************************************************************/
  796. void I_ResumeSong(int handle)
  797. {
  798. //  fprintf (stderr, "I_ResumeSong(%d)\n", handle);
  799.  
  800.   if (music_okay) {
  801.     Mus_Resume(handle);
  802.   }
  803. }
  804.  
  805. /**********************************************************************/
  806. // Registers a song handle to song data.
  807. int I_RegisterSong(void *data)
  808. {
  809. //  fprintf (stderr, "I_RegisterSong(%08x)\n", data);
  810.  
  811.   if (music_okay) {
  812.     return Mus_Register(data);
  813.   } else
  814.     return 2;
  815. }
  816.  
  817. /**********************************************************************/
  818. // Called by anything that wishes to start music.
  819. //  plays a song, and when the song is done,
  820. //  starts playing it again in an endless loop.
  821. // Horrible thing to do, considering.
  822. void
  823. I_PlaySong
  824. ( int        handle,
  825.   int        looping )
  826. {
  827. //  fprintf (stderr, "I_PlaySong(%d,%d)\n", handle, looping);
  828.  
  829.   if (music_okay) {
  830.     Mus_Play(handle, looping);
  831.   }
  832.  
  833.   musicdies = gametic + TICRATE*30;
  834. }
  835.  
  836. /**********************************************************************/
  837. // Stops a song over 3 seconds.
  838. void I_StopSong(int handle)
  839. {
  840. //  fprintf (stderr, "I_StopSong(%d)\n", handle);
  841.  
  842.   if (music_okay) {
  843.     Mus_Stop(handle);
  844.   }
  845.   musicdies = 0;
  846. }
  847.  
  848. /**********************************************************************/
  849. // See above (register), then think backwards
  850. void I_UnRegisterSong(int handle)
  851. {
  852. //  fprintf (stderr, "I_UnRegisterSong(%d)\n", handle);
  853.  
  854.   if (music_okay) {
  855.     Mus_Unregister(handle);
  856.   }
  857.   handle = 0;
  858. }
  859.  
  860. /**********************************************************************/
  861.  
  862.  
  863. /**********************************************************************/
  864. void _STDaudio_cleanup (void)
  865. {
  866.   I_ShutdownSound ();
  867.   I_ShutdownMusic ();
  868. }
  869.  
  870. /**********************************************************************/
  871.